"""
错误处理中间件
统一处理和记录系统错误
"""

import time
import traceback
from typing import Callable
from fastapi import Request, Response
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

from ..logger import logger
from ..models import ErrorResponse


class ErrorHandlingMiddleware(BaseHTTPMiddleware):
    """错误处理中间件"""
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        start_time = time.time()
        
        try:
            response = await call_next(request)
            
            # 记录请求信息
            process_time = time.time() - start_time
            logger.info(
                f"{request.method} {request.url.path} - "
                f"Status: {response.status_code} - "
                f"Time: {process_time:.3f}s"
            )
            
            return response
            
        except Exception as exc:
            # 记录错误详情
            process_time = time.time() - start_time
            error_id = f"ERR_{int(time.time())}_{hash(str(exc)) % 10000:04d}"
            
            logger.error(
                f"Request failed - ID: {error_id} - "
                f"{request.method} {request.url.path} - "
                f"Time: {process_time:.3f}s - "
                f"Error: {str(exc)}",
                exc_info=True
            )
            
            # 返回统一错误响应
            return JSONResponse(
                status_code=500,
                content=ErrorResponse(
                    message="Internal server error",
                    error_code="INTERNAL_ERROR",
                    error_id=error_id,
                    timestamp=time.time()
                ).model_dump()
            )


class RateLimitMiddleware(BaseHTTPMiddleware):
    """简单的速率限制中间件"""
    
    def __init__(self, app, calls_per_minute: int = 60):
        super().__init__(app)
        self.calls_per_minute = calls_per_minute
        self.client_requests = {}
        
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        client_ip = request.client.host
        current_time = time.time()
        
        # 清理过期记录
        self._cleanup_old_requests(current_time)
        
        # 检查速率限制
        if self._is_rate_limited(client_ip, current_time):
            logger.warning(f"Rate limit exceeded for {client_ip}")
            return JSONResponse(
                status_code=429,
                content=ErrorResponse(
                    message="Rate limit exceeded",
                    error_code="RATE_LIMIT_EXCEEDED",
                    timestamp=current_time
                ).model_dump()
            )
        
        # 记录请求
        self._record_request(client_ip, current_time)
        
        return await call_next(request)
    
    def _cleanup_old_requests(self, current_time: float):
        """清理过期的请求记录"""
        cutoff_time = current_time - 60  # 1分钟前
        
        for client_ip in list(self.client_requests.keys()):
            self.client_requests[client_ip] = [
                req_time for req_time in self.client_requests[client_ip]
                if req_time > cutoff_time
            ]
            
            if not self.client_requests[client_ip]:
                del self.client_requests[client_ip]
    
    def _is_rate_limited(self, client_ip: str, current_time: float) -> bool:
        """检查是否超过速率限制"""
        if client_ip not in self.client_requests:
            return False
        
        recent_requests = len(self.client_requests[client_ip])
        return recent_requests >= self.calls_per_minute
    
    def _record_request(self, client_ip: str, current_time: float):
        """记录请求"""
        if client_ip not in self.client_requests:
            self.client_requests[client_ip] = []
        
        self.client_requests[client_ip].append(current_time)


class RequestLoggingMiddleware(BaseHTTPMiddleware):
    """请求日志中间件"""
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        start_time = time.time()
        
        # 记录请求开始
        logger.debug(
            f"Request started: {request.method} {request.url.path} "
            f"from {request.client.host}"
        )
        
        response = await call_next(request)
        
        # 记录请求完成
        process_time = time.time() - start_time
        logger.debug(
            f"Request completed: {request.method} {request.url.path} - "
            f"Status: {response.status_code} - "
            f"Time: {process_time:.3f}s"
        )
        
        # 添加响应头
        response.headers["X-Process-Time"] = str(process_time)
        response.headers["X-Request-ID"] = f"req_{int(start_time)}_{hash(str(request.url)) % 10000:04d}"
        
        return response


class CORSMiddleware(BaseHTTPMiddleware):
    """CORS中间件"""
    
    def __init__(self, app, allow_origins: list = None, allow_methods: list = None):
        super().__init__(app)
        self.allow_origins = allow_origins or ["*"]
        self.allow_methods = allow_methods or ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
        
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        # 处理预检请求
        if request.method == "OPTIONS":
            response = Response()
            self._add_cors_headers(response, request)
            return response
        
        response = await call_next(request)
        self._add_cors_headers(response, request)
        
        return response
    
    def _add_cors_headers(self, response: Response, request: Request):
        """添加CORS头"""
        origin = request.headers.get("origin")
        
        if "*" in self.allow_origins or origin in self.allow_origins:
            response.headers["Access-Control-Allow-Origin"] = origin or "*"
        
        response.headers["Access-Control-Allow-Methods"] = ", ".join(self.allow_methods)
        response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-Requested-With"
        response.headers["Access-Control-Allow-Credentials"] = "true"


class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    """安全头中间件"""
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        response = await call_next(request)
        
        # 添加安全头
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
        response.headers["Content-Security-Policy"] = "default-src 'self'"
        
        return response


class HealthCheckMiddleware(BaseHTTPMiddleware):
    """健康检查中间件"""
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        # 快速响应健康检查请求
        if request.url.path in ["/health", "/ping", "/api/v1/health/ping"]:
            return JSONResponse(
                content={
                    "status": "healthy",
                    "timestamp": time.time()
                }
            )
        
        return await call_next(request)


def setup_middleware(app):
    """设置所有中间件"""
    
    # 健康检查中间件（最先执行）
    app.add_middleware(HealthCheckMiddleware)
    
    # 安全头中间件
    app.add_middleware(SecurityHeadersMiddleware)
    
    # CORS中间件
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],  # 生产环境应该限制具体域名
        allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"]
    )
    
    # 速率限制中间件
    app.add_middleware(
        RateLimitMiddleware,
        calls_per_minute=120  # 每分钟120次请求
    )
    
    # 请求日志中间件
    app.add_middleware(RequestLoggingMiddleware)
    
    # 错误处理中间件（最后执行）
    app.add_middleware(ErrorHandlingMiddleware)
    
    logger.info("All middleware configured successfully")
